package com.paziy.notes.core.notes;

/**
 * Seven main notes
 *
 * @author thecederick@gmail.com (Paziy Evgeniy)
 * @version 0.4
 * @since 0.1 (02.12.13 10:50)
 */
public enum Note {
    C(Accidental.FLAT), //can't be flat
    //Csharp,
    //Dflat,
    D(null),
    //Dsharp,
    //Eflat,
    E(Accidental.SHARP), //can't be sharp
    F(Accidental.FLAT),  //can't be flat
    //Fsharp,
    //Gflat,
    G(null),
    //Gsharp,
    //Aflat,
    A(null),
    //Asharp,
    //Hflat,
    H(Accidental.SHARP); //can't be sharp

    /**
     * Class constant holds first note of octave.
     */
    public static final Note FIRST_NOTE = Note.C;

    /**
     * Class constant holds last note of octave.
     */
    public static final Note LAST_NOTE = Note.H;

    /**
     * Holds next note from current
     */
    private Note next;

    /**
     * Holds previous note from current
     */
    private Note previous;

    /**
     * Initialization of instance fields {next} and {previous}
     * @see Note#next
     * @see Note#previous
     */
    static {
        C.next = D;
        C.previous = H;

        D.next = E;
        D.previous = C;

        E.next = F;
        E.previous = D;

        F.next = G;
        F.previous = E;

        G.next = A;
        G.previous = F;

        A.next = H;
        A.previous = G;

        H.next = C;
        H.previous = A;
    }

    /**
     * Instance variable of Note Type of current Note
     */
    private Accidental illegalAccidental;

    Note(Accidental illegalAccidental) {
        this.illegalAccidental = illegalAccidental;
    }

    /**
     * Returns true if current {Accidental} is allowed.
     * If {Accidental} is null returns false.
     *
     * @return true if allowed
     */
    public boolean isAllowedAccidental(Accidental accidental) {
        return !((accidental == null) || (accidental == illegalAccidental));
    }

    /**
     * Getter for field {next}. Never returns null.
     * For highest note {H} next will be {C}
     * @see Note#next
     *
     * @return next note of current
     */
    public Note getNextNote() {
        return next;
    }

    /**
     * Getter for field {previous}. Never returns null.
     * For highest note {C} previous will be {H}
     * @see Note#previous
     *
     * @return previous note of current
     */
    public Note getPreviousNote() {
        return previous;
    }

}
